﻿using System;
using System.IO;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using ElectronicCommerce.Framework.Logging;

namespace ElectronicCommerce.Framework.Utility
{
    public static class ObjectXmlSerializer
    {
        public static string LogCategoryName = "Framework.ObjectXmlSerializer";

        /// <summary>
        /// deserialize an object from a file
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static T LoadFromXml<T>(string fileName) where T : class
        {
            FileStream fs = null;
            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                return (T)serializer.Deserialize(fs);
            }
            catch (Exception ex)
            {
                Logger.Log(String.Format("Deserialization Fail. File : {0}, Error Message : {1}", fileName, ex.Message));
                return null;
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                }
            }
        }

        /// <summary>
        /// deserialize an object from a file
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public static object LoadFromXml(string fileName, Type type)
        {
            FileStream fs = null;
            try
            {
                XmlSerializer serializer = new XmlSerializer(type);
                fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
                return serializer.Deserialize(fs);
            }
            catch (Exception ex)
            {
                Logger.Log(String.Format("Deserialization Fail. File : {0}, Error Message : {1}", fileName, ex.Message));
                return null;
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                }
            }
        }

        /// <summary>
        /// deserialize an object from a XML Message
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xmlMessage"></param>
        /// <returns>
        ///     Null is returned if any error occurs.
        /// </returns>
        public static T LoadFromXmlMessage<T>(string xmlMessage) where T : class
        {
            StringReader sReader = null;
            try
            {
                XmlSerializer serializer = new XmlSerializer(typeof(T));
                sReader = new StringReader(xmlMessage);
                return (T)serializer.Deserialize(sReader);
            }
            catch (Exception ex)
            {
                Logger.Log(String.Format("Deserialization Fail. XmlMessage: {0} , Error Message : {1}", xmlMessage, ex.Message));
                return null;
            }
            finally
            {
                if (sReader != null)
                {
                    sReader.Dispose();
                }
            }
        }

        /// <summary>
        /// serialize an object to a string value.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="instance"></param>
        /// <returns>
        ///  Null is returned if any error occurs.
        /// </returns>
        public static string ToStringXmlMessage<T>(T instance)
        {
            UTF8StringWriter sr = null;
            try
            {
                XmlSerializer xr = new XmlSerializer(typeof(T));
                StringBuilder sb = new StringBuilder();

                sr = new UTF8StringWriter(sb);
                xr.Serialize(sr, instance);

                return (sb.ToString());
            }
            catch (Exception ex)
            {
                Logger.Log(String.Format("Serialization Fail. Error Message : {0} {1}{2}", ex.Message, Environment.NewLine, ex.StackTrace));
                return null;
            }
            finally
            {
                if (sr != null)
                {
                    sr.Close();
                }
            }
        }

        public static bool SaveXmlToFlie<T>(string fileName, T xmlInfor) where T : class
        {
            try
            {
                string xmlStrInfor = ToStringXmlMessage<T>(xmlInfor);

                if (!string.IsNullOrEmpty(xmlStrInfor))
                {
                    XmlDocument xmlDoc = new XmlDocument();
                    xmlDoc.LoadXml(xmlStrInfor);
                    xmlDoc.Save(fileName);

                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch (Exception ex)
            {
                Logger.Log(String.Format("Save Fail. Error Message : {0}", ex.Message));
                return false;
            }
        }

        private class UTF8StringWriter : StringWriter
        {
            public override Encoding Encoding
            {
                get
                {
                    return Encoding.UTF8;
                }
            }

            public UTF8StringWriter(StringBuilder sb)
                : base(sb)
            {
            }
        }
    }
}
